package controllers

import java.io.File
import java.nio.file.Files

import akka.stream.IOResult
import akka.stream.scaladsl.FileIO
import config.{Global, MyFile}
import javax.inject.Inject
import play.api.libs.json.Json
import play.api.libs.streams.Accumulator
import play.api.mvc.MultipartFormData.FilePart
import play.api.mvc.{AbstractController, Action, AnyContent, ControllerComponents}
import play.core.parsers.Multipart.{FileInfo, FilePartHandler}
import tools._
import utils.{ExecCommand, TableUtils}

import scala.concurrent.{ExecutionContext, Future}
import scala.util.Failure

class ToolsController @Inject()(cc: ControllerComponents)
                               (implicit exec: ExecutionContext) extends AbstractController(cc) with MyFile {

  def toolsPage(page: String) = Action {
    Ok(
      page match {
        case "primerPage" => views.html.tools.primerPage()
        case "musclePage" => views.html.tools.musclePage()
        case "lastzPage" => views.html.tools.lastzPage()
        case "genewisePage" => views.html.tools.genewisePage()
        case "enrichPage" => views.html.tools.enrichPage()
      }
    )
  }

  private def handleFilePartAsFile: FilePartHandler[File] = {
    case FileInfo(partName, filename, contentType, dispositionType) =>
      val file = new File(Global.tmpPath, Global.random)
      val path = file.toPath
      Accumulator(FileIO.toPath(path)).mapFuture {
        case IOResult(_, Failure(error)) => Future.failed(error)
        case IOResult(count, _) =>
          Future.successful(FilePart(partName, filename, contentType, file, count, dispositionType))
      }
  }

  def toolsRun(tools: String): Action[AnyContent] = Action { implicit request =>
    Ok(
      tools match {
        case "genewise" => GeneWise.genewise
        case "enrich" => Enrich.enrichRun
      }
    )
  }

  def toolsFileRun(tools: String) = Action(parse.multipartFormData(handleFilePartAsFile)) { implicit request =>
    Ok(
      tools match {
        case "muscle" => Muscle.muscle
        case "lastz" => Lastz.lastz
      }
    )
  }


  def primer = Action { implicit request =>
    var valid = "true"
    var message = ""
    var result = ""
    try {
      val data = Primer3.primerForm.bindFromRequest.get
      val data2 = Primer3.primerForm2.bindFromRequest.get
      val tmp = Files.createTempDirectory("tmpDir").toString

      val fa = data2.method match {
        case "range" =>
          val cmd = s"${Global.samtools} faidx ${Global.path}/fasta/genome/${data.species}.genome ${data.chr}:${data.start}-${data.end}"
          val execCommand = new ExecCommand
          execCommand.exect(Array(cmd), tmp)
          execCommand.getOutStr.split("\n").tail.mkString
        case "seq" =>
          data2.queryText
      }
      println(tmp)
      val res = Primer3.runPrimer(fa, data, tmp)
      valid = res._1
      message = res._2
      result = res._3
    } catch {
      case e: Exception =>
        valid = "false"
        message = e.getMessage
    }

    Ok(Json.obj("valid" -> valid, "message" -> message, "result" -> result))
  }

  def getGeneNameExample(genome: String) = Action { implicit request =>
    Ok(Json.toJson(TableUtils.exampleGeneName(genome).mkString(",")))
  }


}
